package com.alibaba.basic.service.impl;

import com.alibaba.basic.businessexception.BusinessException;
import com.alibaba.basic.dto.SmsCodeDto;
import com.alibaba.basic.service.IverifyCodeService;
import com.alibaba.basic.util.StrUtils;
import com.alibaba.basic.util.VerifyCodeUtils;
import com.alibaba.user.domain.User;
import com.alibaba.user.mapper.UserMapper;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;

@Service
public class VerifyCodeServiceImpl implements IverifyCodeService {
    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private UserMapper userMapper;

    @Override
    public String getImgCode(String key) {
        // 生成随机的数
        String code = StrUtils.getComplexRandomString(4);

        // 设置概数字存在的时间
        redisTemplate.opsForValue().set(key, code, 5, TimeUnit.MINUTES);
        // 使用工具编码编码成base64
        String base64Str = VerifyCodeUtils.verifyCode(110, 40, code);
        return base64Str;
    }

    /**
     * //手机号码
     * private String phone;
     * //图形验证码
     * private String imageCode;
     * //图形验证码的key
     * private String imageCodeKey;
     */
    @Override
    public void smsCode(SmsCodeDto smsCodeDto) {
        //一：校验 - 空值校验
        // 1.获取手机号
        String phone = smsCodeDto.getPhone();
        // 2.获取验证码
        String imageCode = smsCodeDto.getImageCode();
        // 3.获取验证码key
        String key = smsCodeDto.getImageCodeKey();

        // 4.空值判断
        if (StringUtils.isEmpty(phone)) {
            throw new BusinessException("手机号不能为空");
        }
        if (StringUtils.isEmpty(imageCode)) {
            throw new BusinessException("验证码不能为空");
        }
        // 二、校验验证码是否过期，是否正确
        Object o = redisTemplate.opsForValue().get(key);

        if (o == null) {
            // 为空,验证码时效过期，抛出异常
            throw new BusinessException("验证码过期，请重新发送");
        }
        if (!o.toString().equalsIgnoreCase(imageCode)) {
            throw new BusinessException("验证码错误，请输入正确验证码");
        }
        // 三、判断手机号是否注册过
        // 1.传一个phone查询数据库是否存在手机号一样的对象，判断是否注册过
        User user = userMapper.findByPhone(phone);
        if (user != null) {
            throw new BusinessException("用户已注册，请直接登陆");
        }
        // 四、获取手机验证码是否过期
        // 获取生成的验证码
        Object codeObj = redisTemplate.opsForValue().get("register:" + phone);
        // 创建一个空的变量来装新的code
        String smsCode = null;
        // 判断验证码是否为空,为空直接重新获取一次
        if (codeObj == null) {
            smsCode = StrUtils.getRandomString(4);

        } else {// 不为空就判断验证码时间过了1分钟没限制恶意注册
            // 分割在调用Long打包工具解析成Long类型
            long oldTime = Long.parseLong(codeObj.toString().split(":")[1]);
            // 判断是否小于一分钟,小于1分钟就抛异常
            if (System.currentTimeMillis() - oldTime < 60 * 1000) {
                throw new BusinessException("频繁操作，稍后再试");
            }
            // 超过一分钟就将上面的验证码重新赋值给他
            smsCode = codeObj.toString().split(":")[0];
        }
        // 重新赋值后需要再次保存到redis,并且赋值3分钟
        redisTemplate.opsForValue().set("register:" + phone, smsCode + ":" + System.currentTimeMillis(),
                3, TimeUnit.MINUTES);

        // 用工具类发验证
//        SmsUtils.sendSms(phone,"你的验证码为：" + smsCode + ",有效期为三分钟");
        System.out.println("你的验证码为：" + smsCode + ",有效期为三分钟");
    }

    @Override
    public void binderSmsCode(SmsCodeDto smsCodeDto) {
        //一：校验 - 空值校验
        // 1.获取手机号
        String phone = smsCodeDto.getPhone();

        // 4.空值判断
        if (StringUtils.isEmpty(phone)) {
            throw new BusinessException("手机号不能为空");
        }
        // 三、判断手机号是否注册过
        // 1.传一个phone查询数据库是否存在手机号一样的对象，判断是否注册过
        User user = userMapper.findByPhone(phone);
        if (user != null) {
            throw new BusinessException("用户已注册，请直接登陆");
        }
        // 四、获取手机验证码是否过期
        // 获取生成的验证码
        Object codeObj = redisTemplate.opsForValue().get("binder:" + phone);
        // 创建一个空的变量来装新的code
        String smsCode = null;
        // 判断验证码是否为空,为空直接重新获取一次
        if (codeObj == null) {
            smsCode = StrUtils.getRandomString(4);

        } else {// 不为空就判断验证码时间过了1分钟没限制恶意注册
            // 分割在调用Long打包工具解析成Long类型
            long oldTime = Long.parseLong(codeObj.toString().split(":")[1]);
            // 判断是否小于一分钟,小于1分钟就抛异常
            if (System.currentTimeMillis() - oldTime < 60 * 1000) {
                throw new BusinessException("频繁操作，稍后再试");
            }
            // 超过一分钟就将上面的验证码重新赋值给他
            smsCode = codeObj.toString().split(":")[0];
        }
        // 重新赋值后需要再次保存到redis,并且赋值3分钟
        redisTemplate.opsForValue().set("binder:" + phone, smsCode + ":" + System.currentTimeMillis(),
                3, TimeUnit.MINUTES);

        // 用工具类发验证
//        SmsUtils.sendSms(phone,"你的验证码为：" + smsCode + ",有效期为三分钟");
        System.out.println("你的验证码为：" + smsCode + ",有效期为三分钟");
    }
}
